<template>
  <div id="appChatPage">
    <!-- 顶部栏 -->
    <div class="header-bar">
      <div class="header-left">
        <h1 class="app-name">{{ appInfo?.appName || '网站生成器' }}</h1>
        <a-tag
          v-if="appInfo?.codeGenType"
          :color="getBadgeColorByType(<String>appInfo?.codeGenType)"
          class="code-gen-type-tag"
        >
          {{ formatCodeGenType(appInfo?.codeGenType) }}
        </a-tag>
      </div>
      <!-- 顶部操作按钮栏 -->
      <div class="header-right">
        <a-button @click="reloadPreview" title="刷新" size="small">
          <template #icon>
            <SyncOutlined />
          </template>
        </a-button>
        <a-button v-if="previewUrl" @click="openInNewTab" title="新窗口打开" size="small" >
          <template #icon>
            <ExportOutlined />
          </template>
        </a-button>
        <a-button type="default" @click="showAppDetail" size="small" title="应用详情">
          <template #icon>
            <InfoCircleOutlined />
          </template>
        </a-button>
        <a-button
          type="primary"
          ghost
          @click="downloadCode"
          size="small"
          :loading="downloading"
          title="下载代码"
        >
          <template #icon>
            <FileZipOutlined />
          </template>
        </a-button>

        <a-button type="primary" 
        :disabled="!isOwner"
        @click="deployApp" :loading="deploying" size="small" title="部署">
          <template #icon>
            <RocketOutlined />
          </template>
        </a-button>
      </div>
    </div>

    <!-- 主要内容区域 -->
    <div class="main-content">
      <!-- 左侧对话区域 -->
      <div class="chat-section">
        <!-- 加载更多历史 -->
        <div v-if="hasMore" class="load-more-bar">
          <a-button type="link" :loading="loadingMore" @click="loadMoreHistory">加载更多</a-button>
        </div>
        <!-- 消息区域 -->
        <div class="messages-container" ref="messagesContainer">
          <div
            v-for="(message, index) in sortedMessages"
            :key="message.id ?? message.createdAt ?? index"
            class="message-item"
          >
            <!-- 用户消息气泡 -->
            <div v-if="message.type === 'user'" class="user-message">
              <div class="message-content">
                <MarkdownRenderer v-if="message.content" :content="message.content" />
              </div>
              <div class="message-avatar">
                <a-avatar :src="loginUserStore.loginUser.userAvatar" />
              </div>
            </div>
            <!-- AI消息气泡 -->
            <div v-else class="ai-message">
              <div class="message-avatar">
                <a-avatar :src="aiAvatar" />
              </div>
              <div class="message-content">
                <MarkdownRenderer v-if="message.content" :content="message.content" />
                <div v-if="message.loading" class="loading-indicator">
                  <a-spin size="small" />
                  <span>AI 正在思考...</span>
                </div>
              </div>
            </div>
          </div>
        </div>

        <!-- 用户消息输入框 -->
        <div class="input-container">
          <div class="input-wrapper">
            <a-tooltip v-if="!isOwner" title="无法在别人的作品下对话哦~" placement="top">
              <a-textarea
                v-model:value="userInput"
                placeholder="请描述你想生成的网站，越详细效果越好哦"
                :rows="4"
                :maxlength="1000"
                @keydown.enter.prevent="sendMessage"
                :disabled="isGenerating || !isOwner"
                show-count="true"
              />
            </a-tooltip>
            <a-textarea
              v-else
              v-model:value="userInput"
              placeholder="请描述你想生成的网站，越详细效果越好哦"
              :rows="4"
              :maxlength="1000"
              @keydown.enter.prevent="sendMessage"
              :disabled="isGenerating"
              show-count="true"
            />
            <div class="input-actions">
              <a-button
                type="primary"
                @click="sendMessage"
                :loading="isGenerating"
                :disabled="!isOwner"
              >
                <template #icon>
                  <SendOutlined />
                </template>
              </a-button>
            </div>
          </div>
        </div>
      </div>

      <!-- 右侧网页展示区域 -->
      <div class="preview-section">
        <div class="preview-content">
          <div v-if="!previewUrl && !isGenerating" class="preview-placeholder">
            <div class="placeholder-icon">🌐</div>
            <p>网站文件生成完成后将在这里展示</p>
          </div>
          <div v-else-if="isGenerating" class="preview-loading">
            <a-spin size="large" />
            <p>正在生成网站...</p>
          </div>
          <iframe
            v-else
            :src="previewUrl"
            class="preview-iframe"
            frameborder="0"
            @load="onIframeLoad"
          ></iframe>
        </div>
      </div>
    </div>

    <!-- 应用详情弹窗 -->
    <AppDetailModal
      v-model:open="appDetailVisible"
      :app="appInfo"
      :show-actions="isOwner || isAdmin"
      @edit="editApp"
      @delete="deleteApp"
    />

    <!-- 部署成功弹窗 -->
    <DeploySuccessModal
      v-model:open="deployModalVisible"
      :deploy-url="deployUrl"
      @open-site="openDeployedSite"
    />
  </div>
</template>

<script setup lang="ts">
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { message } from 'ant-design-vue'
import {
  deleteApp as deleteAppApi,
  deployApp as deployAppApi,
  getAppVoById,
} from '@/api/appController'
import { listAppChatHistory } from '@/api/chatHistoryController'
import request from '@/request'

import MarkdownRenderer from '@/components/MarkdownRenderer.vue'
import AppDetailModal from '@/components/AppDetailModal.vue'
import DeploySuccessModal from '@/components/DeploySuccessModal.vue'
import aiAvatar from '@/assets/logo.png'

import {
  ExportOutlined,
  FileZipOutlined,
  InfoCircleOutlined,
  SyncOutlined,
  RocketOutlined,
  SendOutlined,
} from '@ant-design/icons-vue'
import { useLoginUserStore } from '@/stores/LoginUserStore'
import { CodeGenTypeEnum, formatCodeGenType, getBadgeColorByType } from '@/utils/CodeGenTypes'
import { API_BASE_URL, getStaticPreviewUrl } from '@/config/env.ts'

const route = useRoute()
const router = useRouter()
const loginUserStore = useLoginUserStore()

// 应用信息
const appInfo = ref<API.AppVO>()
const appId = ref<string>()

// 对话相关
interface Message {
  type: 'user' | 'ai' | any
  content: string
  loading?: boolean
  id?: number
  createdAt?: number | string
}

const messages = ref<Message[]>([])
const sortedMessages = computed(() =>
  [...messages.value].sort((a, b) => {
    const ta = new Date(a.createdAt || 0).getTime()
    const tb = new Date(b.createdAt || 0).getTime()
    return ta - tb
  }),
)
// 用户Prompt输入框的输入内容
const userInput = ref('')
const isGenerating = ref(false)
const messagesContainer = ref<HTMLElement>()
const hasInitialConversation = ref(false) // 标记是否已经进行过初始对话
// 历史消息分页与游标
const loadingHistory = ref(false)
const loadingMore = ref(false)
const hasMore = ref(false)
// 最后一条消息的创建时间（用于游标查询）
const historyCursorLastCreateTime = ref<string>()
const loadedMessageIds = ref<Set<number>>(new Set())

// 预览相关
const previewUrl = ref('')
const previewReady = ref(false)

// 部署相关
const deploying = ref(false)
const deployModalVisible = ref(false)
const deployUrl = ref('')

// 权限相关
const isOwner = computed(() => {
  return appInfo.value?.userId === loginUserStore.loginUser.id
})

const isAdmin = computed(() => {
  return loginUserStore.loginUser.userRole === 'admin'
})

// 应用详情相关
const appDetailVisible = ref(false)

// 显示应用详情
const showAppDetail = () => {
  appDetailVisible.value = true
}

/**
 * 获取应用信息后：
 * - 加载最近10条历史消息（升序）
 * - 若历史记录≥2条，展示网站
 * - 若为自己应用且历史为空且有 initPrompt，则自动触发初始消息
 */
const fetchAppInfo = async () => {
  const id = route.params.id as string
  if (!id) {
    message.error('应用ID不存在')
    router.push('/')
    return
  }

  appId.value = id

  try {
    const res = await getAppVoById({ id: id as any })
    if (res.data.code === 0 && res.data.data) {
      appInfo.value = res.data.data

      // 先加载最近10条历史消息（升序）
      await loadInitialHistory()

      // 若历史记录至少2条，展示网站
      if (messages.value.length >= 2) {
        updatePreview()
        // 重复刷新一次，保证是最新内容
        reloadPreview();
      }

      // 若为自己应用，且没有历史记录，则自动使用 initPrompt 触发初始消息
      if (
        isOwner.value &&
        messages.value.length === 0 &&
        appInfo.value?.initPrompt &&
        !hasInitialConversation.value
      ) {
        hasInitialConversation.value = true
        await sendInitialMessage(appInfo.value.initPrompt!)
      }
    } else {
      message.error('获取应用信息失败')
      router.push('/')
    }
  } catch (error) {
    console.error('获取应用信息失败：', error)
    message.error('获取应用信息失败')
    router.push('/')
  }
}

// 发送初始消息
const sendInitialMessage = async (prompt: string) => {
  // 添加用户消息
  messages.value.push({
    type: 'user',
    content: prompt,
    createdAt: Date.now(),
  })

  // 添加AI消息占位符
  const aiMessageIndex = messages.value.length
  messages.value.push({
    type: 'ai',
    content: '',
    loading: true,
    createdAt: Date.now(),
  })

  await nextTick()
  scrollToBottom()

  // 开始生成
  isGenerating.value = true
  await generateCode(prompt, aiMessageIndex)
}

// 发送消息
const sendMessage = async () => {
  if (!userInput.value.trim() || isGenerating.value) {
    return
  }

  const message = userInput.value.trim()
  userInput.value = ''

  // 添加用户消息
  messages.value.push({
    type: 'user',
    content: message,
    createdAt: Date.now(),
  })

  // 添加AI消息占位符
  const aiMessageIndex = messages.value.length
  messages.value.push({
    type: 'ai',
    content: '',
    loading: true,
    createdAt: Date.now(),
  })

  await nextTick()
  scrollToBottom()

  // 开始生成
  isGenerating.value = true
  await generateCode(message, aiMessageIndex)
}

/**
 * 历史消息加载与分页
 */
const loadInitialHistory = async () => {
  if (!appId.value) return
  loadingHistory.value = true
  try {
    const res = await listAppChatHistory({
      appId: appId.value as any,
      pageSize: 10,
    })
    if (res.data.code === 0) {
      const records = res.data.data?.records || []
      // 去重
      const newRecords = records.filter((r) => {
        if (!r.id) return true
        const existed = loadedMessageIds.value.has(r.id)
        if (!existed) loadedMessageIds.value.add(r.id)
        return !existed
      })
      // 升序
      newRecords.sort((a, b) => {
        const ta = new Date(a.createTime || 0).getTime()
        const tb = new Date(b.createTime || 0).getTime()
        return ta - tb
      })
      // 游标设为最旧消息时间
      historyCursorLastCreateTime.value = newRecords.length ? newRecords[0].createTime : undefined
      // 映射到页面消息
      messages.value = newRecords.map((r) => ({
        type: (r.messageType || '').toLowerCase() === 'user' ? 'user' : 'ai',
        content: r.message || '',
        id: r.id,
        createdAt: r.createTime,
      }))
      hasMore.value = records.length >= 10
      await nextTick()
      scrollToBottom()
    } else {
      message.error('加载历史消息失败：' + res.data.message)
    }
  } catch (e) {
    console.error('加载历史消息失败：', e)
    message.error('加载历史消息失败')
  } finally {
    loadingHistory.value = false
  }
}

/**
 * 加载更多历史消息
 */
const loadMoreHistory = async () => {
  if (!appId.value || loadingMore.value || !historyCursorLastCreateTime.value) return
  loadingMore.value = true
  try {
    const res = await listAppChatHistory({
      appId: appId.value as any,
      pageSize: 10,
      lastCreateTime: historyCursorLastCreateTime.value,
    })
    if (res.data.code === 0) {
      const records = res.data.data?.records || []
      // 去重
      const newRecords = records.filter((r) => {
        if (!r.id) return true
        const existed = loadedMessageIds.value.has(r.id)
        if (!existed) loadedMessageIds.value.add(r.id)
        return !existed
      })
      // 升序
      newRecords.sort((a, b) => {
        const ta = new Date(a.createTime || 0).getTime()
        const tb = new Date(b.createTime || 0).getTime()
        return ta - tb
      })
      // 更新游标为新的最旧时间
      if (newRecords.length) {
        historyCursorLastCreateTime.value = newRecords[0].createTime
      } else {
        hasMore.value = false
      }
      // 映射并前置
      const prependMessages = newRecords.map((r) => ({
        type: (r.messageType || '').toLowerCase() === 'user' ? 'user' : 'ai',
        content: r.message || '',
        id: r.id,
        createdAt: r.createTime,
      }))
      messages.value = [...prependMessages, ...messages.value]
      hasMore.value = records.length >= 10
    } else {
      message.error('加载更多失败：' + res.data.message)
    }
  } catch (e) {
    console.error('加载更多失败：', e)
    message.error('加载更多失败')
  } finally {
    loadingMore.value = false
  }
}

// 生成代码 - 使用 EventSource 处理流式响应
const generateCode = async (userMessage: string, aiMessageIndex: number) => {
  let eventSource: EventSource | null = null
  let streamCompleted = false

  try {
    // 获取 axios 配置的 baseURL
    const baseURL = request.defaults.baseURL || API_BASE_URL

    // 构建URL参数
    const params = new URLSearchParams({
      appId: appId.value || '',
      message: userMessage,
    })

    const url = `${baseURL}/app/chat/gen/code?${params}`

    // 创建 EventSource 连接
    eventSource = new EventSource(url, {
      withCredentials: true,
    })

    let fullContent = ''

    // 处理接收到的消息
    eventSource.onmessage = function (event) {
      if (streamCompleted) return

      try {
        // 解析JSON包装的数据
        const parsed = JSON.parse(event.data)
        const content = parsed.d

        // 拼接内容
        if (content !== undefined && content !== null) {
          fullContent += content
          messages.value[aiMessageIndex].content = fullContent
          messages.value[aiMessageIndex].loading = false
          scrollToBottom()
        }
      } catch (error) {
        console.error('解析消息失败:', error)
        handleError(error, aiMessageIndex)
      }
    }

    // 处理done事件
    eventSource.addEventListener('done', function () {
      if (streamCompleted) return

      streamCompleted = true
      isGenerating.value = false
      eventSource?.close()

      // 延迟更新预览，确保后端已完成处理
      setTimeout(() => {
        updatePreview()
        // 重复刷新一次，保证是最新内容
        reloadPreview();
      }, 1000)
    })

    // 处理business-error事件（后端限流等错误）
    eventSource.addEventListener('business-error', function (event: MessageEvent) {
      if (streamCompleted) return

      try {
        const errorData = JSON.parse(event.data)
        console.error('SSE业务错误事件:', errorData)

        // 显示具体的错误信息
        const errorMessage = errorData.message || '生成过程中出现错误'
        messages.value[aiMessageIndex].content = `❌ ${errorMessage}`
        messages.value[aiMessageIndex].loading = false
        message.error(errorMessage)

        streamCompleted = true
        isGenerating.value = false
        eventSource?.close()
      } catch (parseError) {
        console.error('解析错误事件失败:', parseError, '原始数据:', event.data)
        handleError(new Error('服务器返回错误'), aiMessageIndex)
      }
    })


    // 处理错误
    eventSource.onerror = function () {
      if (streamCompleted || !isGenerating.value) return
      // 检查是否是正常的连接关闭
      if (eventSource?.readyState === EventSource.CONNECTING) {
        streamCompleted = true
        isGenerating.value = false
        eventSource?.close()

        setTimeout(() => {
          updatePreview()
          // 重复刷新一次，保证是最新内容
          reloadPreview();
        }, 1000)
      } else {
        handleError(new Error('SSE连接错误'), aiMessageIndex)
      }
    }
  } catch (error) {
    console.error('创建 EventSource 失败：', error)
    handleError(error, aiMessageIndex)
  }
}

// 错误处理函数
const handleError = (error: unknown, aiMessageIndex: number) => {
  console.error('生成代码失败：', error)
  messages.value[aiMessageIndex].content = '抱歉，生成过程中出现了错误，请重试。'
  messages.value[aiMessageIndex].loading = false
  message.error('生成失败，请重试')
  isGenerating.value = false
}

// 更新预览
const updatePreview =  () => {
  if (appId.value) {
    const codeGenType = appInfo.value?.codeGenType || CodeGenTypeEnum.HTML
    previewUrl.value = getStaticPreviewUrl(codeGenType, appId.value)
    previewReady.value = true
  }
}
// 刷新页面
const reloadPreview =  () => {
  const codeGenType = appInfo.value?.codeGenType || CodeGenTypeEnum.HTML
  const iframe = document.querySelector('.preview-iframe') as HTMLIFrameElement
  if (iframe) {
    // iframe刷新
    iframe.src = getStaticPreviewUrl(codeGenType, appId?.value || '')
    // 页面刷新
    location.reload();
  }
}

// 滚动到底部
const scrollToBottom = () => {
  if (messagesContainer.value) {
    messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight
  }
}

// 部署应用
const deployApp = async () => {
  if (!appId.value) {
    message.error('应用ID不存在')
    return
  }

  deploying.value = true
  try {
    const res = await deployAppApi({
      appId: appId.value as any,
    })

    if (res.data.code === 0 && res.data.data) {
      deployUrl.value = res.data.data
      deployModalVisible.value = true
      message.success('部署成功')
    } else {
      message.error('部署失败：' + res.data.message)
    }
  } catch (error) {
    console.error('部署失败：', error)
    message.error('部署失败，请重试')
  } finally {
    deploying.value = false
  }
}

// 在新窗口打开预览
const openInNewTab = () => {
  if (previewUrl.value) {
    window.open(previewUrl.value, '_blank')
  }
}

// 打开部署的网站
const openDeployedSite = () => {
  if (deployUrl.value) {
    window.open(deployUrl.value, '_blank')
  }
}

// iframe加载完成
const onIframeLoad = () => {
  previewReady.value = true
}

// 编辑应用
const editApp = () => {
  if (appInfo.value?.id) {
    router.push(`/app/edit/${appInfo.value.id}`)
  }
}

// 删除应用
const deleteApp = async () => {
  if (!appInfo.value?.id) return

  try {
    const res = await deleteAppApi({ id: appInfo.value.id })
    if (res.data.code === 0) {
      message.success('删除成功')
      appDetailVisible.value = false
      router.push('/')
    } else {
      message.error('删除失败：' + res.data.message)
    }
  } catch (error) {
    console.error('删除失败：', error)
    message.error('删除失败')
  }
}

//=================================================== 下载代码相关 ==========================================
const downloading = ref(false)

// 下载代码
const downloadCode = async () => {
  if (!appId.value) {
    message.error('应用ID不存在')
    return
  }
  downloading.value = true
  try {
    const API_BASE_URL = request.defaults.baseURL || ''
    const url = `${API_BASE_URL}/app/download/${appId.value}`
    const response = await fetch(url, {
      method: 'GET',
      credentials: 'include', //携带 cookie
    })
    if (!response.ok) {
      throw new Error(`下载失败: ${response.status}`)
    }
    // 获取文件名
    const contentDisposition = response.headers.get('Content-Disposition')
    const fileName = contentDisposition?.match(/filename="(.+)"/)?.[1] || `app-${appId.value}.zip`
    // 下载文件
    const blob = await response.blob()
    const downloadUrl = URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = downloadUrl
    link.download = fileName
    link.click()
    // 清理
    URL.revokeObjectURL(downloadUrl)
    //message.success('代码下载成功')
  } catch (error) {
    console.error('下载失败：', error)
    message.error('下载失败，请重试')
  } finally {
    downloading.value = false
  }
}

// 页面加载时获取应用信息
onMounted(() => {
  fetchAppInfo()
})

// 清理资源
onUnmounted(() => {
  // EventSource 会在组件卸载时自动清理
})
</script>

<style scoped>
#appChatPage {
  height: 90vh;
  display: flex;
  flex-direction: column;
  background: #fdfdfd;
}

/* 顶部栏 */
.header-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 16px 0 16px;
}

.header-left {
  display: flex;
  align-items: center;
  gap: 12px;
}

.app-name {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: #1a1a1a;
}

.code-gen-type-tag {
  font-size: 12px;
}

.header-right {
  display: flex;
  gap: 12px;
}

/* 主要内容区域 */
.main-content {
  flex: 1;
  display: flex;
  gap: 16px;
  padding: 8px;
  overflow: hidden;
}

/* 左侧对话区域 */
.chat-section {
  flex: 1.5; /* 对话区域比例 */
  display: flex;
  flex-direction: column;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

.messages-container {
  flex: 1;
  padding: 16px;
  overflow-y: auto;
  scroll-behavior: smooth;
}

.message-item {
  margin-bottom: 6px;
}

.user-message {
  display: flex;
  justify-content: flex-end;
  align-items: flex-start;
  gap: 8px;
}

.ai-message {
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  gap: 8px;
}

.message-content {
  max-width: 70%;
  padding: 8px 8px;
  border-radius: 12px;
  line-height: 1.25;
  word-wrap: break-word;
}

.user-message .message-content {
  background: #edf3fe;
  /* 收紧 AI 消息气泡的上下内边距 */
  padding: 0 8px;
}

.ai-message .message-content {
  background: #f5f5f5;
  color: #1a1a1a;
  /* 收紧 AI 消息气泡的上下内边距 */
  padding: 6px 8px;
}
/* 收紧 Markdown 常见块元素的默认上下边距，仅作用于 AI 消息 */
.ai-message .message-content :deep(p),
.ai-message .message-content :deep(ul),
.ai-message .message-content :deep(ol),
.ai-message .message-content :deep(pre),
.ai-message .message-content :deep(blockquote) {
  margin: 2px 0;
}

.message-avatar {
  flex-shrink: 0;
}

.loading-indicator {
  display: flex;
  align-items: center;
  gap: 8px;
  color: #666;
}

/* 输入区域 */
.input-container {
  padding: 14px;
  background: white;
}

.input-wrapper {
  position: relative;
}

.input-wrapper .ant-input {
  padding-right: 50px;
}

.input-actions {
  position: absolute;
  bottom: 8px;
  right: 8px;
}

/* 右侧应用预览区域 */
.preview-section {
  flex: 3;
  display: flex;
  flex-direction: column;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

.preview-content {
  flex: 1;
  position: relative;
  overflow: hidden;
}

.preview-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #666;
}

.placeholder-icon {
  font-size: 48px;
  margin-bottom: 16px;
}

.preview-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #666;
}

.preview-loading p {
  margin-top: 16px;
}

.preview-iframe {
  width: 100%;
  height: 100%;
  border: none;
}

/* 响应式设计 */
@media (max-width: 1024px) {
  .main-content {
    flex-direction: column;
  }

  .chat-section,
  .preview-section {
    flex: none;
    height: 50vh;
  }
}

@media (max-width: 768px) {
  .header-bar {
    padding: 12px 16px;
  }

  .app-name {
    font-size: 16px;
  }

  .main-content {
    padding: 8px;
    gap: 8px;
  }

  .message-content {
    max-width: 85%;
  }
}
</style>
